---
title: 简单封装个对象池
sidebar_position: 8
---
# 简单封装个对象池

看到公司使用 `ObjectPool` 对象池缓存rabbitmq连接

看了下具体实现,感觉用起来太繁琐

需要实现 `IPooledObjectPolicy` 接口, 自定义一个 `Policy`

而这个接口中最主要的可能就是 `Create` 方法, 即在池中无对象的情况下如何创建新的

所以我觉得可以尝试封装一下,简化使用

## 第一版

首先定义一个泛型 `Policy`

`MyPoolPolicy`

```csharp
public class MyPoolPolicy<T> : IPooledObjectPolicy<T>
{
    public static Func<T> CreateFunc = null;
    public static Func<T, bool> ReturnFunc = null;
    public T Create()
    {
        if (CreateFunc == null)
            return default;
        return CreateFunc();
    }
    public bool Return(T obj)
    {
        return ReturnFunc(obj);
    }
}
```

定义两个静态的委托, 修改委托即可改变 `Create` 中的实现

然后简单写一个静态工具方法用于创建对象池

```csharp
public class PoolTool
{
    public static ObjectPool<T> CreatePool<T>(Func<T> create, Func<T, bool> returnFunc = null) where T : class
    {
        MyPoolPolicy<T>.CreateFunc = create;
        returnFunc ??= item => true;
        MyPoolPolicy<T>.ReturnFunc = returnFunc;
        return new DefaultObjectPool<T>(new MyPoolPolicy<T>());
    }
}
```

一般来说 `Return` 不是太重要,可以给个默认的实现

使用的时候就比较简单了

```csharp
var pool = PoolTool.CreatePool(() => {
    // 一些自定义的东西
    return new MyClass {
        ...
    }
});
```

这样就可以获取到一个可用的对象池, 调用 `pool.Get()` 就可以生成一个 `MyClass` 对象

## 第二版

上一版存在一个问题, 由于只有一个静态的委托对象, 所以当我再次调用 `PoolTool.CreatePool<MyClass>()` 传入新委托时, 之前创建的 pool 实现会被修改为传入的新的委托, 这可能会产生一些问题, 虽然在一般情况下一种类型只会有一种实现, 但是封装的时候也必须要考虑的到这种情况

```csharp
public class MyPoolPolicy<T> : IPooledObjectPolicy<T>
{
    /// <summary>
    /// 每个pool实例的index标记,用于从集合中取出对应的委托
    /// </summary>
    public int? Index { get; set; }
    public static Func<int, T> CreateFunc = null;
    public static Func<int, T, bool> ReturnFunc = null;
    public static List<Func<T>> CreateFuncs = new();
    public static List<Func<T, bool>> ReturnFuncs = new();
    public MyPoolObjectPolicy() { }
    public MyPoolObjectPolicy(int index)
    {
        Index = index;
    }

    public T Create()
    {
        return CreateFunc(Index.Value);
    }

    public bool Return(T obj)
    {
        return ReturnFunc(Index.Value, obj);
    }
}

public class PoolTool
{
    public static ObjectPool<T> CreatePool<T>(Func<T> create, Func<T, bool> returnFunc = null) where T : class
    {
        MyPoolPolicy<T>.CreateFuncs.Add(create);
        returnFunc ??= item => true;
        MyPoolPolicy<T>.ReturnFuncs.Add(returnFunc);

        var policy = new MyPoolPolicy<T>(MyPoolPolicy<T>.CreateFuncs.Count - 1);

        MyPoolPolicy<T>.CreateFunc = (index) => MyPoolPolicy<T>.CreateFuncs[index]();
        MyPoolPolicy<T>.ReturnFunc = (index, item) => MyPoolPolicy<T>.ReturnFuncs[index](item);
        return new DefaultObjectPool<T>(policy);
    }
}
```

每次传入的委托会放到 `CreateFuncs,ReturnFuncs` 集合中,

并且每个新建的pool实例都会有一个用于标记的 `Index`

两者配合即可让同一个 `MyPoolPolicy` 拥有多个实现

:::caution
本文只是提供一个简单的思路, 更加复杂的问题需要结合实际情况考虑再做修改
:::












